package com.yourenbang.lingyun.transaction.web.service.impl.pay;

import com.yourenbang.lingyun.constants.enums.AllyActivateRewardStatusEnum;
import com.yourenbang.lingyun.constants.enums.ChannelIdEnums;
import com.yourenbang.lingyun.constants.enums.FundBillType;
import com.yourenbang.lingyun.constants.enums.PlatNoEnums;
import com.yourenbang.lingyun.constants.enums.fund.AccountType;
import com.yourenbang.lingyun.constants.enums.mq.MqEnum;
import com.yourenbang.lingyun.constants.enums.mq.transaction.ChangeFundDTO;
import com.yourenbang.lingyun.core.util.BizAssertUtils;
import com.yourenbang.lingyun.core.util.KLog;
import com.yourenbang.lingyun.core.util.date.DateFormat;
import com.yourenbang.lingyun.core.util.date.LocalDateUtils;
import com.yourenbang.lingyun.domain.*;
import com.yourenbang.lingyun.mapper.*;
import com.yourenbang.lingyun.transaction.web.domain.po.Merchant;
import com.yourenbang.lingyun.transaction.web.domain.po.klks.AppUserActivate;
import com.yourenbang.lingyun.transaction.web.service.pay.PayActivateService;
import com.yourenbang.mcenter.api.model.dto.MqSendMessage;
import com.yourenbang.mcenter.api.service.McenterMqService;
import com.yourenbang.terminal.api.model.dto.RpcTerminalBindDTO;
import com.yourenbang.terminal.api.service.RpcTerminalService;
import com.yourenbang.transaction.api.service.ticket.TicketApiService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

@Slf4j
@Service("payActivateService")
public class PayActivateServiceImpl implements PayActivateService {

    @Autowired
    private AllyMapper allyMapper;
    @Autowired
    private UserBaseMapper userBaseMapper;
    @Autowired
    private Merchant20Mapper merchant20Mapper;
    @Autowired
    private UserMerchantRecommend20Mapper userMerchantRecommend20Mapper;
    @Autowired
    private TerminalPolicyMapper terminalPolicyMapper;
    @Autowired
    private AllyActivateReward20Mapper allyActivateReward20Mapper;
    @Autowired
    private RpcTerminalService terminalService;
    @Autowired
    private McenterMqService mcenterMqService;
    @Autowired
    private TicketApiService ticketApiService;

    /**
     * 激活返现关系
     */
    @Transactional
    @Override
    public void addEposMerBounty(String userId, Short channelId, String sn) {
        KLog.info("【epos激活返现】userId:{}, sn:{},", userId, sn);

        AllyExample allyExample = new AllyExample();
        allyExample.createCriteria()
                .andUserBaseIdEqualTo(userId);
        List<Ally> allys = allyMapper.selectByExample(allyExample);
        if (CollectionUtils.isEmpty(allys)) {
            return;
        }
        Ally ally = allys.get(0);

        UserMerchantRecommend20Example recommend20Example = new UserMerchantRecommend20Example();
        recommend20Example.createCriteria()
                .andUserBaseIdEqualTo(userId);
        List<UserMerchantRecommend20> recommend20s = userMerchantRecommend20Mapper.selectByExample(recommend20Example);
        if (CollectionUtils.isEmpty(recommend20s)) {
            return;
        }
        UserMerchantRecommend20 recommend = recommend20s.get(0);

        //当前用户是盟友 全部给自己
        if (ally.getAllyFlag()) {
            //纪录明细
            saveOpenAmtAccDetail(channelId, userId, userId, AppUserActivate.TOROLEID_ALLY);
        } else {
            AllyExample parentAllyExample = new AllyExample();
            parentAllyExample.createCriteria()
                    .andUserBaseIdEqualTo(recommend.getRecommendUserBaseId());
            List<Ally> parentAllys = allyMapper.selectByExample(parentAllyExample);
            if (CollectionUtils.isEmpty(parentAllys)) {
                return;
            }
            Ally parentAlly = parentAllys.get(0);

            //邀请人是盟友 全部给邀请人
            if (parentAlly.getAllyFlag()) {

                RpcTerminalBindDTO rpcTerminalBindDTO = new RpcTerminalBindDTO();
                rpcTerminalBindDTO.setTerminalSn(sn);
                Terminal epos = terminalService.getBind(rpcTerminalBindDTO).getData();
                if (Objects.isNull(epos)) {
                    KLog.warn("【epos激活返现】未找到绑定机具信息,不返现,userId:{},sn:{},", userId, sn);
                    return;
                }

                if (StringUtils.equals(epos.getAllyUserBaseId(), recommend.getRecommendUserBaseId())) {
                    //纪录明细
                    KLog.info("【epos激活返现】userId:{},邀请人为盟友,绑定返现盟友:{}", userId, recommend.getRecommendUserBaseId());
                    saveOpenAmtAccDetail(channelId, userId, recommend.getRecommendUserBaseId(), AppUserActivate.TOROLEID_ALLY);
                } else {
                    KLog.info("【epos激活返现】userId:{},邀请人为盟友:{}, 但与机器所属人:{}不一致,返现给机器所属人", userId, recommend.getRecommendUserBaseId(), epos.getAllyUserBaseId());
                    //纪录明细
                    saveOpenAmtAccDetail(channelId, userId, epos.getAllyUserBaseId(), AppUserActivate.TOROLEID_ALLY);
                }


            } else {
                KLog.info("【epos激活返现】userId:{},邀请人为商户,绑定返现商户:{}", userId, recommend.getRecommendUserBaseId());
                //纪录明细
                saveOpenAmtAccDetail(channelId, userId, recommend.getRecommendUserBaseId(), AppUserActivate.TOROLEID_MER);

                KLog.info("【epos激活返现】userId:{},邀请人为商户,绑定返现盟友:{}", userId, recommend.getBelongMerchantUserBaseId());
                //纪录明细
                saveOpenAmtAccDetail(channelId, userId, recommend.getBelongMerchantUserBaseId(), AppUserActivate.TOROLEID_ALLY);
            }
        }

    }

    /**
     * 电签激活返现明细
     *
     * @param fromUserId 交押金的用户
     * @param toUserId   返现给谁
     * @param toRole     角色
     */
    private void saveOpenAmtAccDetail(Short channelId, String fromUserId, String toUserId, String toRole) {

        AllyActivateReward20Example countEposOnlyExample = new AllyActivateReward20Example();
        countEposOnlyExample.createCriteria()
                .andFromUserBaseIdEqualTo(fromUserId)
                .andChannelIdIn(Arrays.asList(ChannelIdEnums.epos.getCode(), ChannelIdEnums.epos_p30.getCode(), ChannelIdEnums.p35.getCode(),ChannelIdEnums.k40.getCode()))
                .andTypeEqualTo("1")
                .andToRoleEqualTo(toRole);
        if (allyActivateReward20Mapper.countByExample(countEposOnlyExample) > 0) {
            KLog.warn("【epos激活返现】已存在返现关系,不再记录,fromUserId:{}", fromUserId);
            return;
        }

        UserBase fromUserBase = userBaseMapper.selectByPrimaryKey(fromUserId);
        UserBase toUserBase = userBaseMapper.selectByPrimaryKey(toUserId);
        String remark = "[" + LocalDateTime.now() + "]缴纳押金;";

        AllyActivateReward20 aua = new AllyActivateReward20();
        aua.setFromUserBaseId(fromUserId);
        aua.setFromUserName(fromUserBase == null ? null : fromUserBase.getUserName());
        aua.setToUserBaseId(toUserBase == null ? null : toUserBase.getUserName());
        aua.setType(AppUserActivate.TYPE_AMT);
        aua.setChannelId(channelId);
        aua.setAmount(BigDecimal.ZERO);            //金额0,此处只确定返现关系,具体金额按用户实际绑定机器反
        aua.setFreezeAmount(BigDecimal.ZERO);
        aua.setToRole(toRole);
        aua.setCreateTime(LocalDateTime.now());
        aua.setRemark(remark);
        aua.setVersion(0);
        aua.setStatus(AllyActivateRewardStatusEnum.STATUS_40.getCode());
        allyActivateReward20Mapper.insertSelective(aua);
    }

    /**
     * 电签激活返现
     */
    @Transactional
    @Override
    public void eposMerBounty(Merchant merchant, Terminal terminal) {
        KLog.info("【激活返现】userBaseId:{},sn:{}", merchant.getUserBaseId(), terminal.getTerminalSn());

        TerminalPolicy posAcp = terminalPolicyMapper.selectByPrimaryKey(terminal.getTerminalPolicyId());

        if (posAcp == null) {
            return;
        }
        //过期后 使用 过期返现金额
        if (posAcp.getTerminalPolicyEnddate().isBefore(LocalDateTime.now())) {
            KLog.info("【激活返现】已过期, 使用过期返现金额, userBaseId:{},sn:{}", merchant.getUserBaseId(), terminal.getTerminalSn());
            posAcp.setCashbackAmount(posAcp.getOutdateCashbackAmount());
            posAcp.setMerchantCashbackAmount(posAcp.getOutdateMerchantCashbackAmount());
        }

        if (posAcp.getFakeFreezePercentage() == null) {
            posAcp.setFakeFreezePercentage(new BigDecimal("0.2"));
        }

        //是否积分策略
        boolean isPointPolicy = StringUtils.contains(posAcp.getTerminalPolicyName(), "积分");

        String remark = "绑定" + (isPointPolicy ? "积分策略" : "普通策略") + "机具[" + terminal.getTerminalSn() + "],时间[" + LocalDateTime.now() + "]首刷返现;";

        AllyActivateReward20Example activateReward20Example = new AllyActivateReward20Example();
        activateReward20Example.createCriteria()
                .andTypeEqualTo("1")
                .andChannelIdIn(Arrays.asList(ChannelIdEnums.epos.getCode(), ChannelIdEnums.epos_p30.getCode(), ChannelIdEnums.p35.getCode(), ChannelIdEnums.k40.getCode()))
                .andStatusEqualTo(AllyActivateRewardStatusEnum.STATUS_40.getCode())
                .andFromUserBaseIdEqualTo(merchant.getUserBaseId());
        activateReward20Example.setOrderByClause("to_role asc");

        List<AllyActivateReward20> eposAct = allyActivateReward20Mapper.selectByExample(activateReward20Example);
        //未找到返现关系
        if (CollectionUtils.isEmpty(eposAct)) {
            KLog.warn("【激活返现】未找到返现关系,不返现,userBaseId:{},sn:{}", merchant.getUserBaseId(), terminal.getTerminalSn());
            return;
        }

        //平台补助金额
        BigDecimal subsidyAmt = BigDecimal.ZERO;
        //平台补助冻结金额
        BigDecimal subsidyFreeAmt = BigDecimal.ZERO;
        //冻结金额
        BigDecimal freezeAmt = BigDecimal.ZERO;
        //反给商户的金额
        BigDecimal merAmt = BigDecimal.ZERO;
        //返给盟友的金额
        BigDecimal allyAmt = BigDecimal.ZERO;

        //是否含有 商户返现  如果是150的返现
        boolean hasMer = eposAct.stream().anyMatch(e -> StringUtils.equals(e.getToRole(), AppUserActivate.TOROLEID_MER));

        //包含商户返现
        if (hasMer) {
            KLog.info("【激活返现】包含商户返现, userBaseId:{},sn:{}", merchant.getUserBaseId(), terminal.getTerminalSn());
            AllyActivateReward20 merAct = eposAct.stream().filter(e -> StringUtils.equals(e.getToRole(), AppUserActivate.TOROLEID_MER)).findFirst().orElse(null);
            if (merAct != null) {
                //没有给过此商户 奖励

                AllyActivateReward20Example moreBountySwiping = new AllyActivateReward20Example();
                moreBountySwiping.createCriteria()
                        .andFromUserBaseIdEqualTo(merAct.getFromUserBaseId())
                        .andToUserBaseIdEqualTo(merAct.getToUserBaseId())
                        .andChannelIdEqualTo(ChannelIdEnums.mpos.getCode())
                        .andTypeEqualTo("1")
                        .andStatusIn(Arrays.asList(AllyActivateRewardStatusEnum.STATUS_0.getCode(), AllyActivateRewardStatusEnum.STATUS_20.getCode()));
                if (allyActivateReward20Mapper.countByExample(moreBountySwiping) < 1) {
                    merAmt = posAcp.getMerchantCashbackAmount();    //100
                } else {
                    KLog.info("【激活返现】返现目标商户已收到过此用户的蓝牙激活奖励,目标商户不返现, 返现关系:{} ,userBaseId:{},sn:{}", merAct.toString(), merchant.getUserBaseId(), terminal.getTerminalSn());
                }
            }
        }

        if (isPointPolicy) {
            KLog.info("【激活返现】积分策略，商户的钱先不返, userBaseId:{},sn:{}", merchant.getUserBaseId(), terminal.getTerminalSn());
            //积分策略，商户的钱先不返
            freezeAmt = posAcp.getCashbackAmount().multiply(posAcp.getFakeFreezePercentage()).setScale(2, RoundingMode.HALF_UP).subtract(merAmt);
            allyAmt = posAcp.getCashbackAmount().subtract(merAmt).subtract(freezeAmt);
        } else {
            freezeAmt = posAcp.getCashbackAmount().multiply(posAcp.getFakeFreezePercentage()).setScale(2, RoundingMode.HALF_UP);   //30
            allyAmt = posAcp.getCashbackAmount().subtract(merAmt).subtract(freezeAmt);  //20
        }

        for (AllyActivateReward20 act : eposAct) {
            if (StringUtils.equals(act.getToRole(), AppUserActivate.TOROLEID_MER)) {
                AllyActivateReward20 upaa = new AllyActivateReward20();
                upaa.setAllyActivateRewardId(act.getAllyActivateRewardId());
                upaa.setVersion(act.getVersion());
                upaa.setRemark(act.getRemark() + remark);

                if (isPointPolicy) {
                    upaa.setStatus(AllyActivateRewardStatusEnum.STATUS_10.getCode());       //积分策略，商户100冻结
                    upaa.setFreezeAmount(merAmt);
                    upaa.setAmount(BigDecimal.ZERO);
                    upaa.setFreezeBeginTime(merchant.getTerminalActiveTime() == null ? LocalDateTime.now() : merchant.getTerminalActiveTime());
                    upaa.setFreezeEndTime(DateFormat.DATETIME_DEFAULT.parse("2099-12-31 00:00:00"));
                } else {
                    upaa.setStatus(AllyActivateRewardStatusEnum.STATUS_0.getCode());
                    upaa.setFreezeAmount(BigDecimal.ZERO);
                    upaa.setAmount(merAmt);
                    upaa.setFreezeResultTime(merchant.getTerminalActiveTime() == null ? LocalDateTime.now() : merchant.getTerminalActiveTime());
                }

                upaa.setUpdateTime(LocalDateTime.now());
                upaa.setChannelId(terminal.getChannelId());
                int upaac = allyActivateReward20Mapper.updateByPrimaryKeySelective(upaa);
                BizAssertUtils.assertOne(upaac, "更新激活返现关系失败");

                //非积分策略,商户反100
                if (!isPointPolicy) {
                    //商户可能不返现
                    if (merAmt.compareTo(BigDecimal.ZERO) == 0) {
                        continue;
                    }
                    ChangeFundDTO changeFundDTO = new ChangeFundDTO();
                    changeFundDTO.setAccountType(AccountType.getFullCode(AccountType.MER, PlatNoEnums.KLKS.getCode()));
                    changeFundDTO.setUserBaseId(act.getToUserBaseId());
                    changeFundDTO.setBillType(FundBillType.TYPE_110.getType());
                    changeFundDTO.setChangeAmount(merAmt);
                    changeFundDTO.setOrderNo(merchant.getUserBaseId() + changeFundDTO.getBillType() + act.getChannelId());
                    addAccountMq(changeFundDTO);
                }
            } else if (StringUtils.equals(act.getToRole(), AppUserActivate.TOROLEID_ALLY)) {
                Merchant20 upMer = new Merchant20();
                upMer.setMerchantId(merchant.getMerchantId());
                upMer.setBountyFlag(new Byte("1"));
                int updateCount = merchant20Mapper.updateByPrimaryKeySelective(upMer);
                BizAssertUtils.assertOne(updateCount, "更新通道商户失败");

                AllyActivateReward20 upaa = new AllyActivateReward20();
                upaa.setAllyActivateRewardId(act.getAllyActivateRewardId());
                upaa.setChannelId(terminal.getChannelId());
                upaa.setVersion(act.getVersion());
                upaa.setRemark(act.getRemark() + remark);
                upaa.setAmount(allyAmt);
                upaa.setFreezeAmount(freezeAmt);
                upaa.setFreezeBeginTime(merchant.getTerminalActiveTime() == null ? LocalDateTime.now() : merchant.getTerminalActiveTime());
                if (ChannelIdEnums.epos.isEquals(terminal.getChannelId())) {
                    if (isPointPolicy) {
                        upaa.setFreezeEndTime(DateFormat.DATETIME_DEFAULT.parse("2099-12-31 00:00:00"));
                    } else {
                        upaa.setFreezeEndTime(LocalDateUtils.localDateToLocalDateTime(upaa.getFreezeBeginTime().toLocalDate().plusDays(90)));
                    }
                }
                upaa.setStatus(posAcp.getFakeFreezePercentage().compareTo(BigDecimal.ZERO) == 0 ? AllyActivateRewardStatusEnum.STATUS_0.getCode() : AllyActivateRewardStatusEnum.STATUS_10.getCode());
                upaa.setUpdateTime(LocalDateTime.now());
                int upaac = allyActivateReward20Mapper.updateByPrimaryKeySelective(upaa);
                BizAssertUtils.assertOne(upaac, "更新激活返现关系失败");

                //加账
                ChangeFundDTO changeFundDTO = new ChangeFundDTO();
                changeFundDTO.setAccountType(AccountType.getFullCode(AccountType.ALLY, PlatNoEnums.KLKS.getCode()));
                changeFundDTO.setUserBaseId(act.getToUserBaseId());
                changeFundDTO.setBillType(FundBillType.TYPE_110.getType());
                changeFundDTO.setChangeAmount(upaa.getAmount());
                changeFundDTO.setOrderNo(merchant.getUserBaseId() + changeFundDTO.getBillType() + act.getChannelId());
                addAccountMq(changeFundDTO);
            }
            KLog.info("【激活返现】反给商户的金额:[{}], 返给盟友的金额[{}], 冻结金额:[{}], 平台补助金额:[{}], 平台补助冻结金额:[{}], userBaseId:{}, sn:{}", merAmt, allyAmt, freezeAmt, subsidyAmt, subsidyFreeAmt, merchant.getUserBaseId(), terminal.getTerminalSn());
        }
    }

    /**
     * MQ 加账
     */
    private void addAccountMq(ChangeFundDTO changeFundDTO) {
        MqSendMessage mqSendMessage = new MqSendMessage();
        mqSendMessage.setTopic(MqEnum.MqTopicEnum.topic_fund);
        mqSendMessage.setTag(MqEnum.MqTagEnum.tag_fund);
        mqSendMessage.setSendMsg(changeFundDTO.toJSON());
        mqSendMessage.setMessageKey(changeFundDTO.getOrderNo());
        mcenterMqService.send(mqSendMessage);
    }
}
